﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;

using System.ComponentModel;
using System.Configuration.Install;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Security;
using System.Reflection;

namespace Microsoft.ExternalResearch.CreativeCommons.CustomInstaller
{
    [RunInstaller(true)]
    public partial class CustomAction : System.Configuration.Install.Installer
    {
        #region Error Logger
        private static ILogger _eventLogger;
        public static ILogger eventLogger
        {
            get
            {
                if (_eventLogger == null)
                {
                    _eventLogger = new Logger();
                }
                return _eventLogger;
            }
            set { _eventLogger = value; }
        }
        #endregion

        private const string AssemblyPath = "assemblypath";
        static string installLocation;

        /// <summary>
        /// ALLUSERS parameter passed from the installer.
        /// </summary>
        private const string allUsersInstallationParam = "allUsersInstallation";

        /// <summary>
        /// Registry entry for Creative Commons Add-in for Excel VSTO manifest.
        /// </summary>        
        private static string ExcelRegistryManifestPath = String.Empty;

        /// <summary>
        /// Registry entry for Creative Commons Add-in for PowerPoint VSTO manifest.
        /// </summary>        
        private static string PowerPointRegistryManifestPath = String.Empty;

        /// <summary>
        /// Flag specifying if user had selected addin to be installed for excel
        /// </summary>
        private static bool excelSelected = false;

        /// <summary>
        /// Flag specifying if user had selected addin to be installed for powerPoint
        /// </summary>
        private static bool powerPointSelected = false;

        /// <summary>
        /// Flag specifying if user had selected addin to be installed for word
        /// </summary>
        private static bool wordSelected = false;

        /// <summary>
        /// Registry entry for Creative Commons Add-in for Word VSTO manifest.
        /// </summary>        
        private static string WordRegistryManifestPath = String.Empty;

        ///// <summary>
        ///// Required designer variable.
        ///// </summary>
        //private System.ComponentModel.IContainer components = null;
        public CustomAction()
        {
            InitializeComponent();

            this.Committed += new InstallEventHandler(CustomAction_Committed);
        }

        #region Install Event Handlers
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        protected override void OnBeforeInstall(System.Collections.IDictionary savedState)
        {
            try
            {
                // Check for 64 bit machine.
                if (NativeMethods.Is64Bit() == false)
                    return;

                excelSelected = string.Equals(this.Context.Parameters["excelSelected"], "1");
                powerPointSelected = string.Equals(this.Context.Parameters["powerPointSelected"], "1");
                wordSelected = string.Equals(this.Context.Parameters["wordSelected"], "1");

                string assemblyPath = this.Context.Parameters[AssemblyPath];
                installLocation = assemblyPath.Substring(0, assemblyPath.LastIndexOf(Resource.SLASH, StringComparison.OrdinalIgnoreCase) + 1);

                ExcelRegistryManifestPath = Path.Combine(installLocation, Resource.CreativeCommonExcelAddInManifest);
                ExcelRegistryManifestPath = ExcelRegistryManifestPath + "|" + Resource.VSTOLocal;

                PowerPointRegistryManifestPath = Path.Combine(installLocation, Resource.CreativeCommonPowerPointAddInManifest);
                PowerPointRegistryManifestPath = PowerPointRegistryManifestPath + "|" + Resource.VSTOLocal;

                WordRegistryManifestPath = Path.Combine(installLocation, Resource.CreativeCommonWordAddInManifest);
                WordRegistryManifestPath = WordRegistryManifestPath + "|" + Resource.VSTOLocal;

                base.OnBeforeInstall(savedState);

                Logger.CreateEventSource();
                if (eventLogger == null)
                {
                    eventLogger = new Logger();
                }
                eventLogger.WriteToLog(LogCategory.Installer, Resource.BEFOREINSTALLMSG + Resource.ADDINTITLE);

////Applications should be closed before continuing the install:
//ApplicationIsOpen(Action.Install);

                //Write keys to registry
                WriteTo64BitRegistry();
            }
            catch (ArgumentNullException ex)
            {
                eventLogger.WriteToLog(LogCategory.Installer, Resource.ERRORBEFOREINSTALL, ex.StackTrace);
            }
            catch (SystemException ex)
            {
                eventLogger.WriteToLog(LogCategory.Installer, Resource.ERRORBEFOREINSTALL, ex.StackTrace);
            }
            catch (Exception ex)
            {
                eventLogger.WriteToLog(LogCategory.Installer, Resource.ERRORBEFOREINSTALL, ex.StackTrace);
            }
        }

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        protected override void OnAfterUninstall(IDictionary savedState)
        {
            try
            {
                base.OnAfterUninstall(savedState);

                if (NativeMethods.Is64Bit())
                {
                    DeleteFrom64BitRegistry();
                }

                if (eventLogger != null)
                {
                    eventLogger.Dispose();
                    eventLogger = null;
                }
            }
            catch (SecurityException ex)
            {
                eventLogger.WriteToLog(LogCategory.Installer, Resource.ERRORUNINSTALL, ex.StackTrace);
            }
            catch (UnauthorizedAccessException ex)
            {
                eventLogger.WriteToLog(LogCategory.Installer, Resource.ERRORUNINSTALL, ex.StackTrace);
            }
            catch (Exception ex)
            {
                eventLogger.WriteToLog(LogCategory.Installer, Resource.ERRORUNINSTALL, ex.StackTrace);
            }
        }
        
        void CustomAction_Committed(object sender, InstallEventArgs e)
        {
            try
            {
                //TODO: Get str from resources
                string releaseNotesFileName = "ReleaseNotes.docx";
                Process.Start(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), releaseNotesFileName));
            }
            catch (FileNotFoundException)
            {
                //File was not found in the executing assembly location
            }
            catch (Exception)
            {
            }
        }

        #endregion


        #region Error handling
        /// <summary>
        /// This method handles logging the error.
        /// </summary>
        /// <param name="error">Error to be logged.</param>
        /// <param name="throwError">Variable indicating if the error should be thrown.</param>
        private void HandleRegistryError(string error, bool throwError)
        {
            // Log the error.   
            this.LogMessage(error);

            if (throwError)
            {
                // Throw the Install exception.
                throw new InstallException(error);
            }
        }

        /// <summary>
        /// Writes a message to the console and to the log file for the installation.
        /// </summary>
        /// <param name="message">The message to be logged.</param>
        private void LogMessage(string message)
        {
            if (this.Context != null)
            {
                this.Context.LogMessage(message);
            }
        }

        /// <summary>
        /// Returns the appropriate registry key based on the installation type.
        /// </summary>
        /// <returns></returns>
        private UIntPtr HKeyForInstallType()
        {
            UIntPtr HKEY_CURRENT_USER = (UIntPtr)0x80000001;
            UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;

            string allUsers = base.Context.Parameters[allUsersInstallationParam];
            int allUserInstallation;

            if (!String.IsNullOrEmpty(allUsers) &&
                Int32.TryParse(allUsers, out allUserInstallation) &&
                allUserInstallation == 1)
            {
                return HKEY_LOCAL_MACHINE;
            }
            else
            {
                return HKEY_CURRENT_USER;
            }
        }
        #endregion Error handling


        #region Methods
        ///// <summary>
        ///// Method looks for all the Microsoft Word process which are opened 
        ///// and kills such processes before the installation or uninstalling process
        ///// </summary>
        ///// <param name="currentAction"></param>
        //[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        //private void ApplicationIsOpen(Action currentAction)
        //{
        //    try
        //    {
        //        if (currentAction == Action.Install || currentAction == Action.UnInstall)
        //        {
        //            Process[] wordInstances;
        //            wordInstances = Process.GetProcessesByName(Resource.WINWORD);
        //            if (wordInstances.Length > 0)
        //            {
        //                Alert applicationOpenAlert = new Alert();
        //                applicationOpenAlert.CurrentInstallerAction = currentAction;

        //                if (currentAction == Action.Install)
        //                {
        //                    applicationOpenAlert.lblMessage.Text = Resource.CLOSE_APPLICATIONS_DURING_INSTALL;
        //                }
        //                else if (currentAction == Action.UnInstall)
        //                {
        //                    applicationOpenAlert.lblMessage.Text = Resource.CLOSE_APPLICATIONS_DURING_UNINSTALL;
        //                }

        //                DialogResult alterDialogResult = applicationOpenAlert.ShowDialog();
        //                if (alterDialogResult == DialogResult.Retry)
        //                {
        //                    applicationOpenAlert.Dispose();
        //                    ApplicationIsOpen(currentAction);
        //                }
        //                else if (alterDialogResult == DialogResult.OK)
        //                {
        //                    Process[] openWordInstances = Process.GetProcessesByName(Resource.WINWORD);
        //                    foreach (Process instance in openWordInstances)
        //                    {
        //                        instance.Kill();
        //                    }
        //                }
        //            }
        //        }
        //    }
        //    catch (NullReferenceException ex)
        //    {
        //        eventLogger.WriteToLog(LogCategory.Installer, Resource.ERRORAPPLICATIONOPEN, ex.StackTrace);
        //    }
        //    catch (InvalidOperationException ex)
        //    {
        //        eventLogger.WriteToLog(LogCategory.Installer, Resource.ERRORAPPLICATIONOPEN, ex.StackTrace);
        //    }
        //    catch (Win32Exception ex)
        //    {
        //        eventLogger.WriteToLog(LogCategory.Installer, Resource.ERRORAPPLICATIONOPEN, ex.StackTrace);
        //    }
        //    catch (NotSupportedException ex)
        //    {
        //        eventLogger.WriteToLog(LogCategory.Installer, Resource.ERRORAPPLICATIONOPEN, ex.StackTrace);
        //    }
        //}


        /// <summary>
        /// This method writes the add-in entries to the registry under SOFTWARE\Microsoft 
        /// for 64 bit machines.
        /// </summary>
        private void WriteTo64BitRegistry()
        {
            // Handle to the registry key.
            UIntPtr handle;
            // Handle to the subkey under the Office\Word.
            UIntPtr subKeyHandle;
            // The load behavior of the add-in.
            int loadBehavior = 3;

            const int KEY_WOW64_64KEY = 0x0100;
            const int KEY_QUERY_VALUE = 0x1;

            UIntPtr HKEY_PTR = HKeyForInstallType();

            // Get the handle to the HKLM entry of Office.
            int readResult = NativeMethods.RegOpenKeyEx(HKEY_PTR, @"SOFTWARE\Microsoft\Office\", 0,
              KEY_QUERY_VALUE | KEY_WOW64_64KEY, out handle);

            if (readResult.Equals(0))
            {
                #region Keys_For_Excel

                if (excelSelected)
                {
                    // Create the 'Excel' key if it does not exist.
                    int handleReturnCode = NativeMethods.RegCreateKey(handle, Resource.EXCEL_REGISTRY_KEY, out subKeyHandle);
                    if (!handleReturnCode.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.EXCEL_REGISTRY_KEY), true);
                    }

                    // Create the addin key if it does not exist.
                    int subKeyhandleReturnCode = NativeMethods.RegCreateKey(subKeyHandle, Resource.ADD_INS_REG_KEY, out subKeyHandle);
                    if (!subKeyhandleReturnCode.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.ADD_INS_REG_KEY), true);
                    }

                    // Create the addin key if it does not exist.
                    int subKeyhandleReturnCode1 = NativeMethods.RegCreateKey(subKeyHandle, Resource.EXCEL_ADDIN_REG_KEY, out subKeyHandle);
                    if (!subKeyhandleReturnCode1.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.EXCEL_ADDIN_REG_KEY), true);
                    }

                    // Write the value pairs to the registry.            
                    int addName = NativeMethods.RegSetValueEx(subKeyHandle, Resource.FRIENDLYNAME, IntPtr.Zero, RegistryValueKind.String, Resource.EXCEL_ADDIN_NAME,
                                Resource.EXCEL_ADDIN_NAME.Length * NativeMethods.NativeBytesPerCharacter);
                    if (!addName.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.FRIENDLYNAME), true);
                    }

                    int description = NativeMethods.RegSetValueEx(subKeyHandle, Resource.DESCRIPTIONSTRING, IntPtr.Zero, RegistryValueKind.String,
                        Resource.EXCEL_ADDIN_DESCRIPTION, Resource.EXCEL_ADDIN_DESCRIPTION.Length * NativeMethods.NativeBytesPerCharacter);
                    if (!description.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.DESCRIPTIONSTRING), true);
                    }

                    int word = NativeMethods.RegSetValueEx(subKeyHandle, Resource.LOADBEHAVIORSTRING, IntPtr.Zero, RegistryValueKind.DWord,
                        ref loadBehavior, NativeMethods.Int32ByteSize);
                    if (!word.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.LOADBEHAVIORSTRING), true);
                    }

                    int manifest = NativeMethods.RegSetValueEx(subKeyHandle, Resource.MANIFEST_NAME, IntPtr.Zero, RegistryValueKind.String, ExcelRegistryManifestPath,
                                ExcelRegistryManifestPath.Length * NativeMethods.NativeBytesPerCharacter);
                    if (!manifest.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.MANIFEST_NAME), true);
                    } 
                }
                
                #endregion

                #region Keys_For_PowerPoint

                if (powerPointSelected)
                {
                    // Create the 'PowerPoint' key if it does not exist.
                    int handleReturnCode = NativeMethods.RegCreateKey(handle, Resource.POWERPOINT_REGISTRY_KEY, out subKeyHandle);
                    if (!handleReturnCode.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.POWERPOINT_REGISTRY_KEY), true);
                    }

                    // Create the addin key if it does not exist.
                    int subKeyhandleReturnCode = NativeMethods.RegCreateKey(subKeyHandle, Resource.ADD_INS_REG_KEY, out subKeyHandle);
                    if (!subKeyhandleReturnCode.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.ADD_INS_REG_KEY), true);
                    }

                    // Create the addin key if it does not exist.
                    int subKeyhandleReturnCode1 = NativeMethods.RegCreateKey(subKeyHandle, Resource.POWERPOINT_ADDIN_REG_KEY, out subKeyHandle);
                    if (!subKeyhandleReturnCode1.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.POWERPOINT_ADDIN_REG_KEY), true);
                    }

                    // Write the value pairs to the registry.            
                    int addName = NativeMethods.RegSetValueEx(subKeyHandle, Resource.FRIENDLYNAME, IntPtr.Zero, RegistryValueKind.String, Resource.POWERPOINT_ADDIN_NAME,
                                Resource.POWERPOINT_ADDIN_NAME.Length * NativeMethods.NativeBytesPerCharacter);
                    if (!addName.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.FRIENDLYNAME), true);
                    }

                    int description = NativeMethods.RegSetValueEx(subKeyHandle, Resource.DESCRIPTIONSTRING, IntPtr.Zero, RegistryValueKind.String,
                        Resource.POWERPOINT_ADDIN_DESCRIPTION, Resource.POWERPOINT_ADDIN_DESCRIPTION.Length * NativeMethods.NativeBytesPerCharacter);
                    if (!description.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.DESCRIPTIONSTRING), true);
                    }

                    int word = NativeMethods.RegSetValueEx(subKeyHandle, Resource.LOADBEHAVIORSTRING, IntPtr.Zero, RegistryValueKind.DWord,
                        ref loadBehavior, NativeMethods.Int32ByteSize);
                    if (!word.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.LOADBEHAVIORSTRING), true);
                    }

                    int manifest = NativeMethods.RegSetValueEx(subKeyHandle, Resource.MANIFEST_NAME, IntPtr.Zero, RegistryValueKind.String, PowerPointRegistryManifestPath,
                                PowerPointRegistryManifestPath.Length * NativeMethods.NativeBytesPerCharacter);
                    if (!manifest.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.MANIFEST_NAME), true);
                    } 
                }

                #endregion
                
                #region Keys_For_Word

                if (wordSelected)
                {
                    // Create the 'Word' key if it does not exist.
                    int handleReturnCode = NativeMethods.RegCreateKey(handle, Resource.WORD_REGISTRY_KEY, out subKeyHandle);
                    if (!handleReturnCode.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.WORD_REGISTRY_KEY), true);
                    }

                    // Create the addin key if it does not exist.
                    int subKeyhandleReturnCode = NativeMethods.RegCreateKey(subKeyHandle, Resource.ADD_INS_REG_KEY, out subKeyHandle);
                    if (!subKeyhandleReturnCode.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.ADD_INS_REG_KEY), true);
                    }

                    // Create the addin key if it does not exist.
                    int subKeyhandleReturnCode1 = NativeMethods.RegCreateKey(subKeyHandle, Resource.WORD_ADDIN_REG_KEY, out subKeyHandle);
                    if (!subKeyhandleReturnCode1.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.WORD_ADDIN_REG_KEY), true);
                    }

                    // Write the value pairs to the registry.            
                    int addName = NativeMethods.RegSetValueEx(subKeyHandle, Resource.FRIENDLYNAME, IntPtr.Zero, RegistryValueKind.String, Resource.WORD_ADDIN_NAME,
                                Resource.WORD_ADDIN_NAME.Length * NativeMethods.NativeBytesPerCharacter);
                    if (!addName.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.FRIENDLYNAME), true);
                    }

                    int description = NativeMethods.RegSetValueEx(subKeyHandle, Resource.DESCRIPTIONSTRING, IntPtr.Zero, RegistryValueKind.String,
                        Resource.WORD_ADDIN_DESCRIPTION, Resource.WORD_ADDIN_DESCRIPTION.Length * NativeMethods.NativeBytesPerCharacter);
                    if (!description.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.DESCRIPTIONSTRING), true);
                    }

                    int word = NativeMethods.RegSetValueEx(subKeyHandle, Resource.LOADBEHAVIORSTRING, IntPtr.Zero, RegistryValueKind.DWord,
                        ref loadBehavior, NativeMethods.Int32ByteSize);
                    if (!word.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.LOADBEHAVIORSTRING), true);
                    }

                    int manifest = NativeMethods.RegSetValueEx(subKeyHandle, Resource.MANIFEST_NAME, IntPtr.Zero, RegistryValueKind.String, WordRegistryManifestPath,
                                WordRegistryManifestPath.Length * NativeMethods.NativeBytesPerCharacter);
                    if (!manifest.Equals(0))
                    {
                        this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                            Resource.MANIFEST_NAME), true);
                    } 
                }

                #endregion
            }
            else
            {
                HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                    Resource.REGISTRYERROR), true);
            }
        }

        /// <summary>
        /// This method deletes the add-in entries from the registry under SOFTWARE\Microsoft 
        /// for 64 bit machines.
        /// </summary>
        private void DeleteFrom64BitRegistry()
        {
            const int KEY_WOW64_64KEY = 0x0100;
            const int KEY_QUERY_VALUE = 0x1;
            UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;
            UIntPtr handle;

            UIntPtr HKEY_PTR = HKeyForInstallType();

            #region Delete_Excel_Keys
            int readResult = NativeMethods.RegOpenKeyEx(HKEY_PTR, @"SOFTWARE\Microsoft\Office\Excel\Addins", 0,
                KEY_QUERY_VALUE | KEY_WOW64_64KEY, out handle);
            if (!readResult.Equals(0))
            {
                this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                        Resource.EXCEL_REGISTRY_KEY), false);
            }

            int keyNameCode = NativeMethods.RegDeleteKey(handle, Resource.EXCEL_ADDIN_REG_KEY);
            if (!keyNameCode.Equals(0))
            {
                this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                    Resource.EXCEL_REGISTRY_KEY), false);
            }
            #endregion

            #region Delete_PowerPoint_Keys
            readResult = NativeMethods.RegOpenKeyEx(HKEY_PTR, @"SOFTWARE\Microsoft\Office\PowerPoint\Addins", 0,
                KEY_QUERY_VALUE | KEY_WOW64_64KEY, out handle);
            if (!readResult.Equals(0))
            {
                this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                        Resource.POWERPOINT_REGISTRY_KEY), false);
            }

            keyNameCode = NativeMethods.RegDeleteKey(handle, Resource.POWERPOINT_ADDIN_REG_KEY);
            if (!keyNameCode.Equals(0))
            {
                this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                    Resource.POWERPOINT_REGISTRY_KEY), false);
            }
            #endregion

            #region Delete_Word_Keys
            readResult = NativeMethods.RegOpenKeyEx(HKEY_PTR, @"SOFTWARE\Microsoft\Office\Word\Addins", 0,
                KEY_QUERY_VALUE | KEY_WOW64_64KEY, out handle);
            if (!readResult.Equals(0))
            {
                this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                        Resource.WORD_REGISTRY_KEY), false);
            }

            keyNameCode = NativeMethods.RegDeleteKey(handle, Resource.WORD_ADDIN_REG_KEY);
            if (!keyNameCode.Equals(0))
            {
                this.HandleRegistryError(String.Format(CultureInfo.InvariantCulture, Resource.REGISTRYERROR,
                    Resource.WORD_REGISTRY_KEY), false);
            }
            #endregion
        }
        #endregion
    }

    internal static class NativeMethods
    {
        public const int Int32ByteSize = 4;
        public static int NativeBytesPerCharacter = Marshal.SystemDefaultCharSize;

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegCreateKey")]
        public static extern int RegCreateKey(UIntPtr keyBase, string keyName, out UIntPtr keyHandle);

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegOpenKeyEx")]
        public static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, uint options, int sam, out UIntPtr phkResult);

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegSetValueEx")]
        public static extern int RegSetValueEx(UIntPtr keyBase,
                string valueName, IntPtr reserved, RegistryValueKind type,
                string data, int rawDataLength);

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegSetValueEx")]
        public static extern int RegSetValueEx(UIntPtr keyBase,
                string valueName, IntPtr reserved, RegistryValueKind type,
                ref int data, int rawDataLength);

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegDeleteKey")]
        public static extern int RegDeleteKey(UIntPtr keyHandle, string valueName);

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegDeleteValue")]
        public static extern int RegDeleteValue(UIntPtr keyHandle, string valueName);

        //[DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegQueryValueExW", SetLastError = true)]
        //public static extern int RegQueryValueEx(
        //                                    UIntPtr hKey,
        //                                    string lpValueName,
        //                                    int lpReserved,
        //                                    out uint lpType,
        //                                    System.Text.StringBuilder lpData,
        //                                    ref int lpcbData);

        //[DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegQueryValueEx")]
        //public static extern int RegQueryValueEx(UIntPtr keyBase,
        //        string valueName, IntPtr reserved, ref RegistryValueKind type,
        //        IntPtr zero, ref int dataSize);


        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Winapi)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool IsWow64Process([In] IntPtr hProcess, [MarshalAs(UnmanagedType.Bool)] [Out] out bool lpSystemInfo);

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        public static bool Is64Bit()
        {
            bool retVal;
            IsWow64Process(Process.GetCurrentProcess().Handle, out retVal);
            return retVal;
        }
    }
}
